/*k
 * An I2C driver for the Philips s7611 RTC
 * Copyright 2005-06 Tower Technologies
 *
 * Author: Alessandro Zummo <a.zummo@towertech.it>
 * Maintainers: http://www.nslu2-linux.org/
 *
 * based on the other drivers in this same directory.
 *
 * http://www.semiconductors.philips.com/acrobat/datasheets/s7611-04.pdf
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/slab.h>

#define DRV_VERSION "0.4.3"



#include <mach/pinctrl.h>
#include <linux/input.h>
#include <linux/hrtimer.h>
#include <linux/kthread.h>
#include <linux/delay.h>

#include <dev/s7611_ts.h>
#include <linux/kernel.h>
#include <linux/string.h>
#define CONFIG_BL_KEY 1
static int synaptics_rmi4_i2c_read(struct i2c_client *in_client,
                                   unsigned short addr, unsigned char *data, unsigned short length,
                                   int print);
// struct i2c_client *this_client;
// static unsigned char *wr_buf;
struct input_dev *input_dev;

struct i2c_client *g_dbg_client;


// int gpio_irq = MXS_PIN_TO_GPIO(MXS_PIN_ENCODE(0, 18));

static struct i2c_driver s7611_driver;

struct s7611_data {
	struct input_dev *input_dev;


	struct completion continue_report;
	struct completion thread_run;
	/* 不想从s7611_data查找i2c_client，直接保存它的备份
	* 需要i2c_client->device->device_driver->driver_data->s7611_data
	*/
	struct i2c_client *client_shadow;
	struct timer_list timer;
	struct work_struct work;
	struct task_struct *thread;
	unsigned char *wr_buf;  // 调试用，用于收发大批量i2c数据
	int gpio_irq;

#if 0
	char name[16];
	int page;
#endif

};

// S7611内部某寄存器名字
struct f08_2d_data {
	char type;
	short x;
	short y;
	char z;
	short w;
} __attribute__ ((__packed__));



static ssize_t timeout_show(struct device *dev,
                            struct device_attribute *attr, char *buf)
{

	return sprintf(buf, "%u\n", 13);
}


static int touch_report(struct i2c_client *in_client, char addr);
static int read_finger(struct i2c_client *in_client, char addr);
static int _2byte_addr(struct i2c_client *in_client, char page, char addr_in_page);
static int w_2byte_addr(struct i2c_client *in_client, char page, char addr_in_page,
                        char *data, int len);

static int test(struct i2c_client *in_client, char addr);
static int synaptics_rmi4_i2c_set_page(struct i2c_client *in_client, short addr)
{
	unsigned char tbuf[2];
	unsigned char rbuf[20];
	
	struct i2c_client *client;

	client = in_client;
	int k = 0, i;
	struct i2c_msg msg[1];
	msg[0].addr = 0x20;
	msg[0].flags = 0;
	msg[0].len = 2;
	msg[0].buf = tbuf;

	tbuf[0] = 0xff;
	tbuf[1] = (addr & 0xff00) >> 8;

	int count = sizeof(msg) / sizeof(struct i2c_msg);
	if ((i2c_transfer(client->adapter, msg, count)) != count) {
		dev_err(&client->dev, "%s: set page error\n", __func__);
		return -EIO;
	}
}

static int synaptics_rmi4_i2c_read(struct i2c_client *in_client,
                                   unsigned short addr, unsigned char *data, unsigned short length,
                                   int print)
{
	unsigned char tbuf[2];
	unsigned char rbuf[20];
	struct i2c_client *client;
	struct i2c_msg msg[2];
	client = in_client;

	int k = 0, i;

	synaptics_rmi4_i2c_set_page(in_client, addr);


	msg[0].addr = 0x20;
	msg[0].flags = 0;
	msg[0].len = 1;
	msg[0].buf = tbuf;

	msg[1].addr = 0x20;
	msg[1].flags = I2C_M_RD;
	msg[1].len = length;
	msg[1].buf = data;

	tbuf[0] = addr & 0x00ff;

	int count = sizeof(msg) / sizeof(struct i2c_msg);
	if ((i2c_transfer(client->adapter, msg, count)) != count) {
		dev_err(&client->dev, "%s: read page error\n", __func__);
		return -EIO;
	}

	if (print) {
		for (i = 0; i < length; i++) {
			printk("%2.2x ", data[i]);
		}
		printk("\r\n");
	}
}

static int synaptics_rmi4_i2c_write(struct i2c_client *in_client,
                                    unsigned short addr, unsigned char *data, unsigned short length)
{
	unsigned char tbuf[10];
	unsigned char rbuf[20];
	struct i2c_client *client;
	struct i2c_msg msg[1];
	struct s7611_data *s7611 = i2c_get_clientdata(in_client);
	
	client = in_client;

	int k = 0, i;

	synaptics_rmi4_i2c_set_page(in_client, addr);

	msg[0].addr = 0x20;
	msg[0].flags = 0;
	msg[0].len = length + 1;
	msg[0].buf = s7611->wr_buf;
	s7611->wr_buf[0] = addr & 0x00ff;


   // todo 不用wr_buf，改用足够大的 msg[xxx]
	memcpy(s7611->wr_buf + 1, data, 5);



	int count = sizeof(msg) / sizeof(struct i2c_msg);
	if ((i2c_transfer(client->adapter, msg, count)) != count) {
		dev_err(&client->dev, "%s: read page error\n", __func__);
		return -EIO;
	}
}

static int test(struct i2c_client *in_client, char addr)
{
	unsigned char tbuf[4] = { addr };
	unsigned char rbuf[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

	synaptics_rmi4_i2c_read(in_client, addr, rbuf, sizeof(rbuf), 1);
	return 0;
}
extern int bl_power_on(void);
static int touch_report(struct i2c_client *in_client, char addr)
{
	int i;
	unsigned char rbuf[sizeof(struct f08_2d_data) * 11] = {0};

	synaptics_rmi4_i2c_read(in_client, 0x0008, rbuf, sizeof(rbuf), 0);

	struct f08_2d_data *pdata =  (struct f08_2d_data *)rbuf;
	static int deta = 1;
	struct s7611_data *bdata = i2c_get_clientdata(in_client);
	struct input_dev *input_dev = bdata->input_dev;

	// for (i = 0; i< 4; i++) {
	// 	printk("%d- %d %d\r\n", i, (pdata + i)->x, (pdata+i)->y);
	// }
	if (pdata->type) {
		input_report_abs(input_dev, ABS_X, pdata->x + deta);
		input_report_abs(input_dev, ABS_Y, pdata->y + deta);
		// input_report_abs(input_dev, ABS_X, pdata->y + deta);
		// input_report_abs(input_dev, ABS_Y, pdata->x + deta);
		input_report_abs(input_dev, ABS_PRESSURE, pdata->type);
		complete(&bdata->continue_report);
		deta = deta * -1;
	} else {
		input_report_abs(input_dev, ABS_PRESSURE, pdata->type);
	}
	input_sync(input_dev);
#if defined(CONFIG_BL_KEY)
	bl_power_on();
#endif
}
static int read_finger(struct i2c_client *in_client, char addr)
{
	unsigned char tbuf[4] = { addr };
	unsigned char rbuf[sizeof(struct f08_2d_data) * 11] = {0};
	struct i2c_client *client;
	client = in_client;
	int k = 0;


	// synaptics_rmi4_i2c_set_page(in_client, 0x0008);
	synaptics_rmi4_i2c_read(in_client, 0x0008, rbuf, sizeof(rbuf), 0);


	rbuf[0] = 0x00;
	rbuf[1] = 0x00;
	rbuf[2] = 0x00;
	rbuf[3] = 0x00;
	rbuf[4] = 0x00;
	rbuf[5] = 0x00;
	rbuf[6] = 0x00;
	rbuf[7] = 0x00;
	synaptics_rmi4_i2c_write(in_client, 0x0012, rbuf, 7);

	// synaptics_rmi4_i2c_set_page(in_client, 0x0012);
	synaptics_rmi4_i2c_read(in_client, 0x0012, rbuf, sizeof(rbuf), 0);

	int i;

	struct f08_2d_data *pdata =  (struct f08_2d_data *)rbuf;
	printk("type\tX\tY\tz\tW\r\n");
	for (i = 0; i < 5; i++) {
		printk("%d\t%d\t%d\t%d\t%d\t\r\n", pdata->type, pdata->x, pdata->y, pdata->z, pdata->w);
		pdata++;

	}
}

static int _2byte_addr(struct i2c_client *in_client, char page, char addr_in_page)
{
	unsigned char tbuf[4] = { page };
	unsigned char rbuf[20] = {0};
	struct i2c_client *client;
	client = in_client;
	int k = 0;

	tbuf[0] = page;
	tbuf[1] = addr_in_page;
	struct i2c_msg msg[] = {
		{ 0x20, 0, 2, tbuf },	/* setup read ptr */
		{ 0x20, I2C_M_RD, sizeof(rbuf), rbuf },	/* read status + date */
	};

	int count = sizeof(msg) / sizeof(struct i2c_msg);
	/* read registers */
	if ((i2c_transfer(client->adapter, msg, count)) != count) {
		dev_err(&client->dev, "%s: read error\n", __func__);
		return -EIO;
	}
	int i;
	printk("page 0x%2.2x(%d)\r\n", page, addr_in_page);
	for (i = 0; i < sizeof(rbuf); i++) {
		printk("%2.2x ", rbuf[i]);
	}
	printk("\r\n");
}
static int w_2byte_addr(struct i2c_client *in_client, char page, char addr_in_page,
                        char *data, int len)
{
	unsigned char tbuf[4] = { page };
	// page 2
	// 18 05 14 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
	unsigned char rbuf[20] = {0x1f, 0x1f, 0x14, 0x1f, 0x1f};
	struct i2c_client *client;
	client = in_client;
	int k = 0;

	tbuf[0] = page;
	tbuf[1] = addr_in_page;
	struct i2c_msg msg[] = {
		{ 0x20, 0, 2, tbuf },	/* setup read ptr */
		// { 0x20, 0, 1, tbuf },	/* setup read ptr */
		{ 0x20, 0, len, rbuf },	/* read status + date */
	};

	int count = sizeof(msg) / sizeof(struct i2c_msg);
	/* read registers */
	if ((i2c_transfer(client->adapter, msg, count)) != count) {
		dev_err(&client->dev, "%s: read error\n", __func__);
		return -EIO;
	}
	int i;

}

static int _enable_irq(struct i2c_client *in_client)
{


	unsigned char tbuf[4];
	unsigned char rbuf[20] = {0x1f, 0x1f, 0x14, 0x1f, 0x1f};
	struct i2c_client *client;

	client = in_client;

	int k = 0;

	tbuf[0] = 0x07;
	struct i2c_msg msg[] = {
		{ 0x20, 0, 1, tbuf },	/* setup read ptr */
		{ 0x20, I2C_M_RD, 1, rbuf },	/* read status + date */
	};

	int count = sizeof(msg) / sizeof(struct i2c_msg);
	/* read registers */
	if ((i2c_transfer(client->adapter, msg, count)) != count) {
		dev_err(&client->dev, "%s: read error\n", __func__);
		return -EIO;
	}

}



#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>




#define CNT_BATTERY (1)

struct misc_s7611_data {
	char name[16];
	int page;
};


static ssize_t name_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;

	return snprintf(buf, PAGE_SIZE, "%s\n", pdata->name);
}


/**
 * @brief	调试用
 * @remarks
 *  echo 0x0007 >   /sys/class/misc/battery0/page
 * @see
 */

static ssize_t s7611_page_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;
	char *after;
	struct i2c_client *client = to_i2c_client(dev);
	printk("client %x %x\r\n", client, dev);
	pdata->page = simple_strtoul(buf, &after, 16);
	// test(client, pdata->page);
	// test(this_client, pdata->page);
	return count;
}


static ssize_t mutil_finger_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;
	char *after;


	// read_finger(/*todo client*/, 0x08);
	return count;
}

static ssize_t _2addr_write_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;
	char *after;
	short addr;
	char value;
	addr = simple_strtoul(buf, &after, 16);
	value = simple_strtoul(buf + 5, &after, 16);

	// w_2byte_addr(/*todo client*/, (addr & 0xff00) >> 8, addr & 0x00ff, value, 1);
	return count;
}


static ssize_t pen_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;
	char *after;
	struct i2c_client *client = g_dbg_client;//to_i2c_client(dev);
	char rbuf[5];

	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);
	// /* 关闭手套模式 */
	
	if (buf[0] == '1') {
		// 全部关闭
		rbuf[3] = 0x3;
	}
	else if (buf[0] == '0') {
		rbuf[3] = 0x01;
	}

	synaptics_rmi4_i2c_write(client, 0x001d, rbuf, sizeof(rbuf));
	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);
	// printk("client %x %x\r\n", client, dev);
	// pdata->page = simple_strtoul(buf, &after, 16);
	return count;
}

static ssize_t glove_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;
	struct i2c_client *client = g_dbg_client;//to_i2c_client(dev);
	char rbuf[5];
	
	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);
	return snprintf(buf, PAGE_SIZE, "%s\n", pdata->name);
}

static ssize_t glove_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;
	char *after;
	struct i2c_client *client = g_dbg_client;//to_i2c_client(dev);
	char rbuf[5];
	int number;

	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);
	// /* 关闭手套模式 */
	
	if (buf[0] == '1') {
		// 全部关闭
		rbuf[0] = 0xe3;// 0xc9也行
	}
	else if (buf[0] == '0') {
		rbuf[0] = 0xc3;// 0xc9也行
	}
	
	// number = simple_strtoul(buf, &after, 16);
	// rbuf[0] = number;
	// printk("number = %d\r\n", number);
	synaptics_rmi4_i2c_write(client, 0x001d, rbuf, sizeof(rbuf));
	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);
	// printk("client %x %x\r\n", client, dev);
	// pdata->page = simple_strtoul(buf, &after, 16);
	return count;
}

static ssize_t pen_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
	struct misc_s7611_data *pdata = (struct misc_s7611_data *)dev->platform_data;
	struct i2c_client *client = g_dbg_client;//to_i2c_client(dev);
	char rbuf[5];
	
	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);
	return snprintf(buf, PAGE_SIZE, "%s\n", pdata->name);
}




static DEVICE_ATTR(
    en_glove, S_IWUSR | S_IRUGO, glove_show, glove_store);
static DEVICE_ATTR(
    en_pen, S_IWUSR | S_IRUGO, pen_show, pen_store);

static DEVICE_ATTR(
    name, S_IRUGO, name_show, NULL);
static DEVICE_ATTR(
    page, S_IWUSR | S_IRUGO, NULL, s7611_page_store);

static DEVICE_ATTR(
    mutil_finger, S_IWUSR | S_IRUGO, NULL, mutil_finger_store);

static DEVICE_ATTR(
    _2addr_write, S_IWUSR | S_IRUGO, NULL, _2addr_write_store);
static struct miscdevice *pmisc;




int success_irq = 0;
static void gpio_keys_timer(unsigned long _data)
{
	unsigned char rbuf[1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	struct i2c_client *client = (struct i2c_client *)_data;
	struct s7611_data *s7611 = i2c_get_clientdata(client);
	
	touch_report(client, NULL);

	synaptics_rmi4_i2c_read(client, 0x0007, rbuf, 1, 0);

	enable_irq(gpio_to_irq(s7611->gpio_irq));

}
static void gpio_keys_work_func(struct work_struct *work)
{
	unsigned char rbuf[1] = {0};
	struct s7611_data *s7611 =
	    container_of(work, struct s7611_data, work);


	touch_report(s7611->client_shadow, NULL);
	synaptics_rmi4_i2c_read(s7611->client_shadow, 0x0007, rbuf, 1, 0);

	enable_irq(gpio_to_irq(s7611->gpio_irq));
}
static irqreturn_t s7611_ts_interrupt(int irq, void *dev_id)
{
	struct s7611_data *s7611 = (struct s7611_data *)dev_id;
//printk("ddddddddddd\r\n");
	disable_irq_nosync(gpio_to_irq(s7611->gpio_irq));
	schedule_work(&s7611->work);
//	printk("----------------\r\n");
	return IRQ_HANDLED;
}
int thread_detect_touch_keep_down(void *arg)
{
	struct s7611_data *s7611 = (struct s7611_data *)arg;

	while(!kthread_should_stop()) {
		msleep(10);
		// 等待 complete 被调用，
		if (wait_for_completion_timeout(&s7611->continue_report, msecs_to_jiffies(1000))) {
			touch_report(s7611->client_shadow, NULL);
		}
	}

	complete(&s7611->thread_run);
	return 0;
}
int _create_input_dev(struct i2c_client *client)
{
	struct input_dev *input_dev = NULL;
	input_dev = input_allocate_device();
	if (!input_dev) {
		printk("failed to allocate input device\n");
		return NULL;
	}

	// ts->input_dev = input_dev;

	set_bit(EV_SYN, input_dev->evbit);
	set_bit(EV_ABS, input_dev->evbit);
	set_bit(EV_KEY, input_dev->evbit);

#ifdef CONFIG_FT5X0X_MULTITOUCH
	set_bit(ABS_MT_TRACKING_ID, input_dev->absbit);
	set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
	set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);
	set_bit(ABS_MT_POSITION_X, input_dev->absbit);
	set_bit(ABS_MT_POSITION_Y, input_dev->absbit);

	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 2048, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 1024, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2000, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 1000, 0, 0);
#else
	set_bit(ABS_X, input_dev->absbit);
	set_bit(ABS_Y, input_dev->absbit);
	set_bit(ABS_PRESSURE, input_dev->absbit);
	set_bit(BTN_TOUCH, input_dev->keybit);

	input_set_abs_params(input_dev, ABS_X, 0, 1000, 0, 0);
	input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 2000, 0 , 0);
#endif
	input_dev->name = "S6711-ts";
	int err;
	err = input_register_device(input_dev);
	if (err) {
		input_free_device(input_dev);
		printk("failed to register input device %d\n", err);
		return NULL;
	}
	return input_dev;
}
/**
 * @brief	启动一个定时器、一个work、一个内核线程，
 * @remarks
 * 如果可以控制触屏IRQ上拉，那么就没有必要启动内核线程
 * @see
 */

int _start_hard_job(struct i2c_client *client)
{
	struct s7611_data *s7611 = i2c_get_clientdata(client);

	init_completion(&s7611->continue_report);    // 报告内核线程有新的输入
	init_completion(&s7611->thread_run);         // 通知内核线程退出
	s7611->thread = kthread_run(thread_detect_touch_keep_down, s7611, "s6711d");

	setup_timer(&s7611->timer, gpio_keys_timer, client);
	INIT_WORK(&s7611->work, gpio_keys_work_func);


	int err, irq = gpio_to_irq(s7611->gpio_irq);

	// 最后一个参数是s7611，在free_irq里也必须使用该参数，不嫩给传递NULL
	err = request_irq(irq, s7611_ts_interrupt, IRQF_TRIGGER_FALLING , "s6711", s7611);
	if (err < 0) {
		dev_err(&client->dev, "%s: request irq\n", __func__);
		return -1;
	}

	success_irq = 1;
	return 0;
}
// 读一次触屏数据，使得中断信号自行变高
void _chip_irq_pull_up(struct i2c_client *client)
{
	int rbuf[1];
	synaptics_rmi4_i2c_read(client, 0x0007, rbuf, 1, 0);
}


static int s7611_probe(struct i2c_client *client,
                       const struct i2c_device_id *id)
{
	struct s7611_platform_data *pdata;
	struct s7611_data *s7611;
	struct input_dev *tinput_dev;
	int err = 0;


	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		return -ENODEV;
	}

	s7611 = kzalloc(sizeof(struct s7611_data), GFP_KERNEL);
	if (!s7611) {
		return -ENOMEM;
	}
	i2c_set_clientdata(client, s7611);
	

	tinput_dev = _create_input_dev(client);
	if (!tinput_dev) {
		dev_err(&client->dev, "%s: create input device\n", __func__);
		return 0;
	}
	pdata = client->dev.platform_data;
	s7611->client_shadow = client;
	s7611->gpio_irq      = pdata->gpio_irq;
	s7611->input_dev     = tinput_dev;
	s7611->wr_buf = kzalloc(256, GFP_KERNEL);
	g_dbg_client = client;
	// /* 关闭手套模式 */
	char rbuf[5],i ;
	// synaptics_rmi4_i2c_read(client, 0x001d, rbuf, 1, 0);
	// printk("--- %x\r\n", rbuf[0]);
	// rbuf[0] = 0x01;
	// synaptics_rmi4_i2c_write(client, 0x001d, rbuf, 1);
	
	// synaptics_rmi4_i2c_read(client, 0x001d, rbuf, 1, 0);
	// printk("--- %x\r\n", rbuf[0]);
	
	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);

	// 全部关闭
	rbuf[0] = 0xc3;// 0xc9也行
	rbuf[3] = 0x01;

	// 全部打开
	rbuf[0] = 0xe9;
	rbuf[3] = 0x03;

	// 仅关闭笔
	rbuf[0] = 0xe9;
	rbuf[3] = 0x01;// 失败

	// 关闭手套(实际上是关闭笔)
	rbuf[0] = 0xc3;
	rbuf[3] = 0x03;	

	// 关闭手套(实际上是关闭笔)
	rbuf[0] = 0xc9;
	rbuf[3] = 0x03;	

	synaptics_rmi4_i2c_write(client, 0x001d, rbuf, sizeof(rbuf));
	synaptics_rmi4_i2c_read(client, 0x001d, rbuf, sizeof(rbuf), 1);
	// for (i = 0;i < sizeof(rbuf); i++) {
	// 	printk("--- %x\r\n", rbuf[i]);	
	// }
	

	_start_hard_job(client);
	_chip_irq_pull_up(client);

	return 0;

exit_kfree:
	kfree(s7611);
	return err;
}
static int s7611_remove(struct i2c_client *client)
{
	struct s7611_data *s7611 = i2c_get_clientdata(client);

	if (s7611->thread) {
		kthread_stop(s7611->thread);
	}
	if (s7611->input_dev) {
		input_unregister_device(s7611->input_dev);
		input_free_device(s7611->input_dev);
	}
	if (success_irq) {
		free_irq(gpio_to_irq(s7611->gpio_irq), s7611);
	}
	kfree(s7611);

	return 0;
}

static const struct i2c_device_id s7611_id[] = {
	{ "s7611", 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, s7611_id);

static struct i2c_driver s7611_driver = {
	.driver		= {
		.name	= "s7611",
	},
	.probe		= s7611_probe,
	.remove		= s7611_remove,
	.id_table	= s7611_id,
};
int __init s7611_init(void)
{
#if 1
	int                    i, err;
	char                   name[16];
	struct device         *this_dev;
	struct miscdevice     *tpmisc;
	struct misc_s7611_data *pdata, *tpdata;



	pmisc = kzalloc(sizeof(struct miscdevice) * CNT_BATTERY, GFP_KERNEL);
	pdata = kzalloc(sizeof(struct misc_s7611_data) * CNT_BATTERY, GFP_KERNEL);
	// s7611->wr_buf = kzalloc(256, GFP_KERNEL);

	tpmisc = pmisc, tpdata = pdata;
	for (i = 0; i < CNT_BATTERY; i++) {
		snprintf(name, sizeof(name), "s7611-%d", i);
		tpmisc->name  = name;
		tpmisc->minor = MISC_DYNAMIC_MINOR;
		tpmisc->fops  = NULL;
		misc_register(tpmisc);

		this_dev                = tpmisc->this_device;
		this_dev->platform_data = tpdata;

		tpdata->page         = 0;
		strncpy(tpdata->name, name, sizeof(((struct misc_s7611_data *)(0))->name));

		device_create_file(this_dev, &dev_attr_en_pen);
		device_create_file(this_dev, &dev_attr_en_glove);
		// device_create_file(this_dev, &dev_attr_name);
		// device_create_file(this_dev, &dev_attr_page);
		// device_create_file(this_dev, &dev_attr__2addr_write);
		// device_create_file(this_dev, &dev_attr_mutil_finger);
		tpmisc++, tpdata++;


	}
	;
#endif

	i2c_add_driver(&s7611_driver);

	return 0;
}

void __exit s7611_exit(void)
{
#if 1
	int i;
	struct miscdevice *tpmisc;

	if (input_dev) {
		input_unregister_device(input_dev);
		input_free_device(input_dev);

	}

	if (pmisc) {
		tpmisc = pmisc;
		for (i = 0; i < CNT_BATTERY; i++) {
			misc_deregister(tpmisc);
			tpmisc++;
		}
		kfree(pmisc);
	}
#endif
	i2c_del_driver(&s7611_driver);
}


MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

module_init(s7611_init);
module_exit(s7611_exit);
